import { useEffect, useState } from 'react';

import AMapLoader from '@amap/amap-jsapi-loader';
import { CloseOutlined, DeleteOutlined, HighlightOutlined, SaveOutlined } from '@ant-design/icons';
import * as turf from '@turf/turf';
import { Input, message } from 'antd';
import { map } from 'lodash-es';

import config from '@/config/amap';

import type { Units } from '@turf/helpers';

import './index.scss';

/**
 * 地图坐标点类型
 */
export interface LocationPoint {
  lng: number; // 经度
  lat: number; // 纬度
}

/**
 * 地址信息类型
 */
export interface AddressInfo {
  location: LocationPoint; // 坐标位置
  address: string; // 地址描述
}

/**
 * 绘制信息类型
 */
export interface DrawInfo {
  address: string; // 中心点地址
  location: LocationPoint; // 中心点坐标
  area: string; // 区域面积（平方米）
}

/**
 * 路径数据类型
 */
export type PathData = number[][]; // 路径点数组 [[lng, lat], ...]

/**
 * 绘制类型
 */
export type DrawType = 'polyline' | 'polygon' | 'rectangle' | 'circle';

/**
 * 地图模式类型
 */
export type MapType = 'drawType' | 'addressType';

/**
 * 详情数据类型
 */
export interface DetailData {
  address?: string; // 地址
  location?: LocationPoint; // 坐标
  pathData?: PathData; // 路径数据
  drawInfo?: DrawInfo; // 绘制信息
  isDetail?: boolean; // 是否为详情模式（只读）
}

/**
 * 搜索结果项类型
 */
export interface SearchResultItem {
  id: string; // 唯一标识
  name: string; // 名称
  address?: string; // 地址
  location: LocationPoint; // 坐标
  formatted_address?: string; // 格式化地址
}

/**
 * AmapBox 组件属性类型
 */
export interface AmapBoxProps {
  /** 地图模式：drawType-绘制模式，addressType-地址选择模式 */
  mapType?: MapType;
  /** 是否显示地图 */
  open?: boolean;
  /** 标记点标题 */
  makerTitle?: string;
  /** 标记点图标类名 */
  makerIcon?: string;
  /** 取消回调 */
  onCancel?: () => void;
  /** 确认回调 - drawType模式返回 {pathData, drawInfo}，addressType模式返回 AddressInfo */
  onOk?: (values: { pathData: PathData; drawInfo: DrawInfo } | AddressInfo) => void;
  /** 详情数据 */
  detail?: DetailData;
}

/**
 * 绘制样式配置
 */
const drawOptions = {
  fillColor: '#00b0ff', // 填充颜色
  strokeColor: '#80d8ff', // 边框颜色
  strokeOpacity: 0.8, // 边框透明度
  fillOpacity: 0.4, // 填充透明度
};

/**
 * 高德地图API类型定义
 */
interface AMapAPI {
  Map: new (container: string, options: Record<string, unknown>) => AMapInstance;
  Marker: new (options: Record<string, unknown>) => AMapMarker;
  MouseTool: new (map: AMapInstance) => AMapMouseTool;
  Geocoder: new (options: Record<string, unknown>) => AMapGeocoder;
  AutoComplete: new (options: Record<string, unknown>) => AMapAutoComplete;
  Polygon: new (options: Record<string, unknown>) => AMapPolygon;
  LngLat: new (lng: number, lat: number) => AMapLngLat;
}

interface AMapInstance {
  clearMap(): void;
  getCenter(): [number, number];
  setCenter(center: [number, number]): void;
  add(overlay: AMapPolygon): void;
  setFitView(): void;
}

interface AMapMarker {
  setMap(map: AMapInstance): void;
  moveTo(position: [number, number], options: Record<string, unknown>): void;
  on(event: string, callback: (e: unknown) => void): void;
}

interface AMapMouseTool {
  on(event: string, callback: (e: unknown) => void): void;
  close(clear: boolean): void;
  polyline(options: Record<string, unknown>): void;
  polygon(options: Record<string, unknown>): void;
  rectangle(options: Record<string, unknown>): void;
  circle(options: Record<string, unknown>): void;
}

interface AMapGeocoder {
  getAddress(lngLat: [number, number], callback: (status: string, result: unknown) => void): void;
}

interface AMapAutoComplete {
  search(keyword: string, callback: (status: string, result: unknown) => void): void;
}

interface AMapPolygon {
  getPath(): Array<{ lat: number; lng: number }>;
}

interface AMapLngLat {
  lat: number;
  lng: number;
}

/**
 * 高德地图相关实例声明
 */
declare global {
  interface Window {
    myMap: AMapInstance;
    AMap: AMapAPI;
    _AMapSecurityConfig: {
      securityJsCode: string;
    };
  }
}

// 地图相关实例变量
let myMap: AMapInstance | null = null;
let mouseTool: AMapMouseTool | null = null;
let polygon: AMapPolygon | null = null;
let geocoder: AMapGeocoder | null = null;
let autoComplete: AMapAutoComplete | null = null;
let locationMaker: AMapMarker | null = null;

/**
 * AmapBox 高德地图组件
 * 支持地址选择和区域绘制两种模式
 */
export default function AmapBox(props: AmapBoxProps) {
  const { open = false, mapType, detail = {}, makerIcon, makerTitle } = props;

  // 消息提示
  const [messageApi, contextHolder] = message.useMessage();

  // 路径数据状态
  const [pathData, setPathData] = useState<PathData>([]);

  // 搜索结果列表
  const [searchList, setSearchList] = useState<SearchResultItem[]>([]);

  // 是否正在绘制
  const [isDraw, setIsDraw] = useState<boolean>(false);

  // 绘制信息状态
  const [drawInfo, setDrawInfo] = useState<DrawInfo>({
    address: '',
    location: { lng: 0, lat: 0 },
    area: '',
  });

  // 地址信息状态
  const [address, setAddress] = useState<AddressInfo>({
    location: { lng: 0, lat: 0 },
    address: '',
  });
  /**
   * 初始化数据信息
   * @param open 是否打开
   * @param detail 详情数据
   */
  const initDataInfo = (open: boolean, detail: DetailData) => {
    if (open) {
      console.log('detail', detail);
      if (detail.address) {
        if (mapType === 'addressType') {
          // 地址选择模式：设置地址信息并创建标记
          setAddress({
            address: detail.address,
            location: detail.location || { lng: 0, lat: 0 },
          });
          createMaker();
          if (locationMaker && detail?.location?.lng && detail?.location?.lat && myMap) {
            locationMaker.moveTo([detail.location.lng, detail.location.lat], {
              duration: 500,
              delay: 500,
              autoRotation: false,
            });
            myMap.setCenter([detail.location.lng, detail.location.lat]);
          }
        }
        if (mapType === 'drawType') {
          // 绘制模式：设置绘制信息和路径数据
          console.log('pathData', detail?.pathData);
          if (detail.drawInfo) {
            setDrawInfo(detail.drawInfo);
          }
          if (detail.pathData) {
            setPathData(detail.pathData);
            initDraw({ points: detail.pathData });
          }
        }
      }
    } else {
      // 重置状态
      setDrawInfo({
        address: '',
        location: { lng: 0, lat: 0 },
        area: '',
      });
      setAddress({
        location: { lng: 0, lat: 0 },
        address: '',
      });
    }
  };
  // useEffect(() => {
  //   initDataInfo(open,detail)
  // }, [open, detail])

  useEffect(() => {
    // console.log('myMap', myMap, open, mapType);
    if (myMap || !open) {
      return;
    }
    window._AMapSecurityConfig = {
      securityJsCode: config.amapCode,
    };
    AMapLoader.load({
      key: config.amapKey, // 申请好的Web端开发者 Key，调用 load 时必填
      version: '2.0', // 指定要加载的 JS API 的版本，缺省时默认为 1.4.15
      plugins: ['AMap.MoveAnimation', 'AMap.MouseTool', 'AMap.Geocoder', 'AMap.AutoComplete'],
    })
      .then((AMap: AMapAPI) => {
        window.myMap = myMap = new AMap.Map('map-box', {
          // viewMode: '2d',
          zoom: 14,
          center: [104.6417, 28.7513],
          // mapStyle: 'amap://styles/light',
          // mapStyle: 'amap://styles/grey',
        });
        // 地图实例创建成功
        geocoder = new AMap.Geocoder({
          // adcode: "530923" 临沧市 citycode: "0883"
          // city: "530923",
          radius: 1000, //以已知坐标为中心点，radius为半径，返回范围内兴趣点和道路信息
          extensions: 'all', //返回地址描述以及附近兴趣点和道路信息，默认“base”
        });
        if (mapType === 'drawType') {
          // 创建鼠标绘图工具
          mouseTool = new AMap.MouseTool(myMap);
          // 添加绘制事件
          mouseTool.on('draw', drawOverlays);
        }

        if (mapType === 'addressType') {
          createMaker();
          //输入提示
          autoComplete = new AMap.AutoComplete({
            // city: "530923",
          });
          console.log('AMap loaded successfully');
        }
        initDataInfo(open, detail);
      })
      .catch((error: Error) => {
        console.error('高德地图加载失败:', error);
        messageApi.error('地图加载失败，请检查网络连接');
      });
  }, [open]);

  useEffect(() => {
    return () => {
      if (!open) {
        myMap = null;
      }
    };
  }, [open]);

  /**
   * 创建可拖拽的位置标记
   */
  const createMaker = () => {
    if (myMap) {
      // 清除地图上的所有覆盖物
      myMap?.clearMap();

      // 创建自定义标记
      locationMaker = new window.AMap.Marker({
        position: myMap.getCenter(), // 标记位置（地图中心）
        size: 18, // 标记大小
        content: `<div class="custom-content-marker" title="${makerTitle}">
        <img src="//webapi.amap.com/theme/v1.3/markers/b/mark_bs.png" alt="" />
        <span class="iconfont ${makerIcon}"></span>
        </div>`,
        // offset: new window.AMap.Pixel(-0, 1), // 偏移量
        draggable: true, // 设置为可拖拽
        cursor: 'move', // 鼠标样式
      });

      // 将标记添加到地图
      if (locationMaker) {
        locationMaker.setMap(myMap);

        // 监听标记拖拽结束事件
        locationMaker.on('dragend', function (e: unknown) {
          console.log('标记拖拽结束', e);
          markerMoved(e);
        });
      }
    }
  };

  /**
   * 标记移动事件处理函数
   * @param e 拖拽事件对象
   */
  const markerMoved = (e: unknown) => {
    // 获取标记的新位置坐标
    const lngLat = (e as { target: { _position: [number, number] } }).target._position;

    // 使用地理编码器进行逆地理编码（坐标转地址）
    if (geocoder) {
      geocoder.getAddress(
        lngLat,
        function (status: string, result: { regeocode?: { formattedAddress: string } }) {
          console.log('逆地理编码结果', result);
          if (status === 'complete' && result.regeocode) {
            const formattedAddress = result.regeocode.formattedAddress;
            // 更新地址状态
            setAddress({
              location: {
                lat: lngLat[1], // 纬度
                lng: lngLat[0], // 经度
              },
              address: formattedAddress,
            });
          } else {
            messageApi.error('根据经纬度查询地址失败');
          }
        }
      );
    }
  };
  /**
   * 初始化绘制（从详情进来的时候）
   * @param initData 初始化数据
   */
  const initDraw = (initData: { points: number[][] }) => {
    const paths = initData.points;
    if (!myMap) {
      return;
    }

    const newPath: AMapLngLat[] = [];
    paths.forEach((v: number[]) => {
      const p = new window.AMap.LngLat(v[0], v[1]);
      newPath.push(p);
    });

    // 创建绘制的多边形对象
    polygon = new window.AMap.Polygon({
      path: newPath, // 设置路径
      ...drawOptions,
    });

    // 添加绘制的多边形对象到地图
    if (polygon && myMap) {
      myMap.add(polygon);
      myMap.setFitView();
    }
  };
  /** 绘制结束 */
  const drawOverlays = (e: unknown) => {
    const drawEvent = e as { obj?: { getPath?: () => Array<{ lat: number; lng: number }> } };
    console.log('e', drawEvent.obj?.getPath);
    let path: Array<{ lat: number; lng: number }> = [];
    if (drawEvent.obj?.getPath) {
      path = drawEvent.obj.getPath(); // 获取绘制的路径
    }

    // 处理绘制的路径数据，您可以在这里对路径进行操作或保存
    console.log('绘制的路径：', path);
    // 处理路径
    const newPoints: ReturnType<typeof turf.point>[] = [];
    path.forEach((item: { lat: number; lng: number }) => {
      newPoints.push(turf.point([item.lat, item.lng]));
    });
    const options: {
      units: Units;
      maxEdge: number;
    } = { units: 'miles', maxEdge: 1 };
    const points = turf.concave(turf.featureCollection(newPoints), options);
    // let points = turf.convex(turf.featureCollection(newPoints));
    console.log('points', points);
    // 计算区域面积 与中心点
    if (points?.geometry) {
      // 面积
      const area = turf.area(points?.geometry).toFixed(2); // 平方米
      console.log('area', area);
      let info = {
        ...drawInfo,
        area: area,
      };
      // setDrawInfo({
      //   ...drawInfo,
      //   area: area
      // })
      // 中心点
      const center = turf.center(points?.geometry);
      if (center?.geometry?.coordinates) {
        let loc = center?.geometry?.coordinates;
        loc = [+loc[1].toFixed(6), +loc[0].toFixed(6)];
        info = {
          ...info,
          location: {
            lng: loc[0],
            lat: loc[1],
          },
        };
        // 计算中心点的 的位置信息
        // 计算中心点的地址
        if (geocoder) {
          geocoder.getAddress(loc as [number, number], function (status: string, result: unknown) {
            const geocodeResult = result as { regeocode?: { formattedAddress: string } };
            if (status === 'complete' && geocodeResult.regeocode) {
              const formattedAddress = geocodeResult.regeocode.formattedAddress;
              console.log('status', status, result, formattedAddress);
              info = {
                ...info,
                address: formattedAddress,
              };
            } else {
              messageApi.open({
                type: 'error',
                content: '根据经纬度查询地址失败',
              });
            }
          });
        }
        setTimeout(() => {
          setDrawInfo(info);
        }, 500);
      }
    }

    const newPath: AMapLngLat[] = [];
    // 存经纬度信息
    const pathData: number[][] = [];
    points?.geometry?.coordinates[0].forEach(v => {
      const coords = v as number[];
      pathData.push(coords);
      const p = new window.AMap.LngLat(coords[1], coords[0]);
      newPath.push(p);
    });
    console.log('pathData', pathData);
    setPathData(pathData);

    // 创建绘制的多边形对象
    polygon = new window.AMap.Polygon({
      path: newPath, // 设置路径
      ...drawOptions,
    });
    if (myMap && polygon) {
      // 添加绘制的多边形对象到地图
      myMap.add(polygon);
    }

    // 继续开启绘制模式
    if (mouseTool) {
      mouseTool.close(true);
    }
    setIsDraw(false);
  };
  /**
   * 指定关闭
   */
  const handleClose = () => {
    if (props?.onCancel) {
      props.onCancel();
    }
    handleClear();
  };
  /** 开始绘制 */
  const handleDraw = (type: 'polyline' | 'polygon' | 'rectangle' | 'circle') => {
    if (myMap) {
      myMap.clearMap();
    }
    setIsDraw(true);
    let drawOptions: Record<string, unknown> = {
      borderWeight: 1, // 线条宽度，默认为 1
      strokeColor: '#80d8ff', // 线条颜色
      lineJoin: 'round', // 折线拐点连接处样式
      strokeOpacity: 0.8, // 设置线条透明度
    };
    if (type != 'polyline') {
      drawOptions = {
        fillColor: '#00b0ff',
        fillOpacity: 0.4, // 设置线条透明度
        strokeColor: '#80d8ff',
        strokeOpacity: 0.8, // 设置线条透明度
      };
    }
    if (mouseTool) {
      (mouseTool as unknown as Record<string, (options: Record<string, unknown>) => void>)[type](
        drawOptions
      );
    }
  };
  /**
   * 清空地图和绘制工具
   */
  const handleClear = () => {
    setIsDraw(false);
    if (myMap) {
      myMap.clearMap();
    }
    if (mouseTool) {
      mouseTool.close(true);
    }
  };
  /** 保存 */
  const handleSave = () => {
    if (props?.onOk) {
      if (mapType === 'drawType') {
        // 返回 drawInfo： 中心点的经纬度 中心点的 位置信息 以及区域面积，pathData 巡查范围的点位信息
        props?.onOk({
          pathData,
          drawInfo,
        });
      }
      if (mapType === 'addressType') {
        //返回信息与经纬度
        props?.onOk(address);
      }
    }
    handleClear();
  };

  /**
   * 处理输入框变化事件
   * @param e 输入事件
   */
  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    console.log('输入值变化:', e.target.value);
    setAddress({ ...address, address: e.target.value });
    setSearchList([]);
    if (e.target.value && autoComplete) {
      autoComplete.search(e.target.value, function (status: string, result: unknown) {
        console.log('搜索状态:', status, result);
        const searchResult = result as { tips?: SearchResultItem[] };
        if (status === 'complete' && searchResult.tips) {
          console.log('搜索结果:', result);
          setSearchList(searchResult.tips);
        } else {
          handleSearch();
          // messageApi.error("配额已经用完")
        }
      });
    } else {
      setSearchList([]);
    }
  };
  // , 120)

  /** 点击查询 然后进行逆地址查询 */
  const handleSearch = () => {
    // 调用高德的地图进行查询
    console.log('123', address);
    fetch(
      `https://restapi.amap.com/v3/geocode/geo?address=${address.address}&key=${config.amapWebKey}&city="临沧"`
    )
      .then(res => res.json())
      .then(
        (res: {
          geocodes?: Array<{ location: string; formatted_address: string; [key: string]: unknown }>;
        }) => {
          console.log('搜索响应:', res);
          // geocodes 是高德地图API返回的字段名
          if (res.geocodes) {
            const newSearchList = res.geocodes.map(v => {
              const loc = v.location.split(',');
              return {
                ...v,
                address: v.formatted_address,
                location: {
                  lng: Number(loc[0]),
                  lat: Number(loc[1]),
                },
              } as SearchResultItem;
            });
            setSearchList(newSearchList);
          }
        }
      );
  };

  return (
    <>
      <div className={`map-box-wrap ${open ? 'open' : 'close'}`}>
        <div id="map-box" className={`map-box ${isDraw ? 'draw' : ''}`}></div>
        <div className="close-btn" onClick={handleClose}>
          <CloseOutlined />
        </div>
        {/*
         * isDetail 详情页面不显示操作，编辑新增显示
         */}
        {mapType === 'drawType' && !detail.isDetail && (
          <div className="tools-btn">
            <div className="btn-draw" onClick={() => handleDraw('polyline')}>
              <span className="icon">
                <HighlightOutlined />
              </span>
              <span className="title">画 笔</span>
            </div>
            {/* <div className="btn-draw" onClick={() => handleDraw('polygon')}>
            <span className='icon'><HighlightOutlined /></span>
            <span className="title">多边形</span>
          </div> */}
            <div className="btn-draw" onClick={() => handleDraw('rectangle')}>
              <span className="icon">
                <HighlightOutlined />
              </span>
              <span className="title">矩 形</span>
            </div>
            <div className="btn-draw" onClick={() => handleDraw('circle')}>
              <span className="icon">
                <DeleteOutlined />
              </span>
              <span className="title">圆 形</span>
            </div>
            <div className="btn-clear" onClick={handleClear}>
              <span className="icon">
                <DeleteOutlined />
              </span>
              <span className="title">清 除</span>
            </div>
            <div className="btn-draw" onClick={handleSave}>
              <span className="icon">
                <SaveOutlined />
              </span>
              <span className="title">保 存</span>
            </div>
          </div>
        )}
        {mapType === 'addressType' && (
          <div className="address-box">
            <div className="top-box">
              <div className="input-box address">
                <div className="label">地址：</div>
                <div className="item-search value">
                  <Input.Search
                    onSearch={handleSearch}
                    onChange={handleInputChange}
                    value={address.address}
                    allowClear
                    className="js-input"
                    placeholder="请输入地址名称搜索"
                  />
                  {searchList.length > 0 && (
                    <div className="search-list">
                      {map(searchList, (v, k) => {
                        return (
                          <div
                            key={v.id + k}
                            onClick={() => {
                              setAddress({
                                ...address,
                                address: v.address && v.address.length > 0 ? v.address : v.name,
                                location: {
                                  lng: v.location.lng,
                                  lat: v.location.lat,
                                },
                              });
                              setSearchList([]);
                              // 移动定位
                              if (locationMaker) {
                                locationMaker.moveTo([v.location.lng, v.location.lat], {
                                  duration: 500,
                                  delay: 500,
                                  autoRotation: false,
                                });
                              }
                            }}
                            className="search-item"
                          >
                            {' '}
                            {v.name}
                            {v.address && v.address.length > 0 && (
                              <span className="unit">({v.address})</span>
                            )}
                          </div>
                        );
                      })}
                    </div>
                  )}
                </div>
              </div>
            </div>
            <div className="bottom-box">
              <div className="input-box location">
                <div className="label">经纬度：</div>
                <div className="item-search value">
                  <Input
                    readOnly
                    className="js-input"
                    value={Object.values(address.location).join()}
                  />
                </div>
              </div>
              <div className="btn-box" onClick={handleSave}>
                <span>保存</span>
              </div>
            </div>
          </div>
        )}
      </div>
      {contextHolder}
    </>
  );
}

//  <AmapBox mapType='addressType' open={mapOpen} onCancel={mapCancel} onOk={mapOk} detail={{}}/>
// <AmapBox mapType='drawType' open={mapOpen} onCancel={mapCancel} onOk={mapOk} detail={mapDetail} />
